package dao

import (
	"context"
	"errors"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/trace"
	"gorm.io/gorm"
	"time"
)

type FileDao interface {
	List(ctx context.Context, page, limit int, types uint8) ([]File, int, error)
	Export(ctx context.Context, page, limit, export int) ([]Data, int, error)
	Insert(ctx context.Context, file File) error
	UpdateName(ctx context.Context, id int64, name string) error
	Delete(ctx context.Context, id int64) error
	ExportData(ctx context.Context, page, limit int) ([]Data, error)
}

var (
	ErrDataTooMuch = errors.New("数据过多，已邮件的形式发送给您")
)

type fileDao struct {
	db     *gorm.DB
	tracer trace.Tracer
}

func NewFileDao(db *gorm.DB) FileDao {
	return &fileDao{
		db:     db,
		tracer: otel.Tracer("File服务-Dao层"),
	}
}

func (f *fileDao) List(ctx context.Context, page, limit int, types uint8) ([]File, int, error) {
	var file []File
	limit = limit
	offset := limit * (page - 1)

	var tatol int64
	db := f.db.Model(&File{}).WithContext(ctx)
	if types > 0 {
		db = db.Where("type = ?", types)
	}
	err := db.Count(&tatol).Error
	if err != nil {
		return file, 0, err
	}
	err = db.Limit(limit).Offset(offset).Order("id desc").Find(&file).Error
	return file, int(tatol), err
}

func (f *fileDao) Insert(ctx context.Context, file File) error {
	now := time.Now().UnixMilli()
	file.CreateTime = now
	file.UpdateTime = now
	err := f.db.WithContext(ctx).Create(&file).Error
	return err
}

func (f *fileDao) UpdateName(ctx context.Context, id int64, name string) error {
	return f.db.Model(&File{}).WithContext(ctx).Where("id = ? ", id).Update("old_name", name).Error
}

func (f *fileDao) Delete(ctx context.Context, id int64) error {
	//TODO 要是其他地方使用了图片库里面的数据记得在删除的时候检验一下  使用 image字段 进行校验

	return f.db.WithContext(ctx).Where("id = ? ", id).Delete(&File{}).Error
}

func (f *fileDao) Export(ctx context.Context, page, limit, export int) ([]Data, int, error) {
	spanCtx, span := f.tracer.Start(ctx, "File服务-Dao层: Export")
	defer span.End()
	var (
		data   []Data
		offset int
		tatol  int64
	)
	offset = limit * (page - 1)

	db := f.db.Model(&Data{}).WithContext(spanCtx)

	err := db.Count(&tatol).Error
	if err != nil {
		return data, 0, err
	}
	if export == 1 {
		return data, int(tatol), ErrDataTooMuch
	} else {
		err = db.Limit(limit).Offset(offset).Order("id desc").Find(&data).Error
	}
	return data, int(tatol), err
}

func (f *fileDao) ExportData(ctx context.Context, page, limit int) ([]Data, error) {
	var data []Data

	offset := limit * (page - 1)

	err := f.db.WithContext(ctx).Limit(limit).Offset(offset).Order("id desc").Find(&data).Error
	return data, err
}

type File struct {
	ID         int64 `gorm:"primaryKey,autoIncrement"`
	Type       uint8 `gorm:"default:1"`
	OldName    string
	NewName    string
	FileType   string
	Size       string
	Image      string
	UpdateTime int64
	CreateTime int64
}

type Data struct {
	ID         int64 `gorm:"primaryKey,autoIncrement"`
	Title      string
	Content    string
	UpdateTime int64
	CreateTime int64
}
